package ar.uba.fi.tecnicas.testing;

import ar.uba.fi.tecnicas.fabrica.*;
import ar.uba.fi.tecnicas.fabrica.exceptions.*;
import ar.uba.fi.tecnicas.testing.mock.ConfiguracionTipoMaquinaMock;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

public class PiezaTest extends TestCase 
{
	private ConfiguracionTipoMaquinaMock confTipoMaquina = ConfiguracionTipoMaquinaMock.instance;
	
	private TipoMateriaPrima madera = new TipoMateriaPrima("Madera",5,"kg");
	
	public void testPiezaCreadaSinMateriaPrima()
	{
		ArrayList<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		boolean piezaCreada = true;
		try
		{
			new Pieza(materias);
		}
		catch(Exception ex)
		{
			piezaCreada = false;
		}
		
		assertFalse("La pieza se creo sin materia prima.", piezaCreada);
	}
	
	public void testCrearPiezaConMateriaPrima()
	{
		ArrayList<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		materias.add(new MateriaPrima(madera, 100));
		
		boolean piezaCreada = true;
		try
		{
			new Pieza(materias);
		}
		catch(Exception ex)
		{
			piezaCreada = false;
		}
		
		assertTrue("La pieza no se pudo crear con materia prima.", piezaCreada);
	}
	
	public void testPiezaAplicarMismaTransformacionConsecutivamente()
	{
		ArrayList<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		materias.add(new MateriaPrima(madera, 100));
		boolean repetirTransformacion = true;

		try
		{
			Pieza pieza = new Pieza(materias);
			
			Transformacion esmaltar = new Transformacion("Esmaltar");
			
			pieza.transformar(esmaltar, 80);
			pieza.transformar(esmaltar, 90);
		}
		catch(TransformacionInvalidaException ex)
		{
			repetirTransformacion = false;
		}
		catch(Exception ex)
		{			
		}
		
		assertFalse("Se pudo aplicar la misma transformacion consecutivamente a la misma pieza.", repetirTransformacion);
	}
	
	public void testPiezaAplicarDiferentesTransformaciones()
	{
		ArrayList<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		materias.add(new MateriaPrima(madera, 100));
		boolean repetirTransformacion = true;

		try
		{
			Pieza pieza = new Pieza(materias);
			
			Transformacion esmaltar = new Transformacion("Esmaltar");
			Transformacion pintar = new Transformacion("Pintar");
			
			pieza.transformar(esmaltar, 80);
			pieza.transformar(pintar, 90);
		}
		catch(TransformacionInvalidaException ex)
		{
			repetirTransformacion = false;
		}
		catch(Exception ex)
		{
		}
		
		assertTrue("No se pudieron aplicar dos transformaciones diferentes consecutivamente a la misma pieza.", repetirTransformacion);
	}
	
	public void testInsertarPiezaEnDosMaquinasDiferentesSimultaneamente()
	{
		Maquina horno = null;
		Maquina esmaltadora = null;
		
		try
		{
			horno = new Maquina(
					this.confTipoMaquina.getItem("Horno"),
					new PosicionTerreno(10, 10));
			esmaltadora = new Maquina(
					this.confTipoMaquina.getItem("Esmaltadora"),
					new PosicionTerreno(10, 10));
		}catch (Exception e) {}
		
		ArrayList<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		materias.add(new MateriaPrima(madera, 100));
		
		boolean insertado = true;
		
		try
		{
			Pieza pieza = new Pieza(materias);
			
			horno.recibir(pieza);
			insertado = esmaltadora.recibir(pieza);
		}
		catch(Exception ex)
		{
		}
		
		assertFalse("Se inserto una pieza en dos maquinas diferentes.", insertado);
	}
	
	public void testInsertarPiezaEnDosMaquinasDiferentesSacandolaPrimero()
	{
		Maquina horno = null;
		Maquina esmaltadora = null;
		
		try
		{
			horno = new Maquina(
					this.confTipoMaquina.getItem("Horno Rapido"),
					new PosicionTerreno(10, 10));
			esmaltadora = new Maquina(
					this.confTipoMaquina.getItem("Esmaltadora"),
					new PosicionTerreno(10, 10));
		}catch (Exception e) {}
		
		List<MateriaPrima> materias = new ArrayList<MateriaPrima>();
		materias.add(new MateriaPrima(madera, 100));
		
		boolean insertado = true;
		
		try
		{
			Pieza pieza = new Pieza(materias);
			
			horno.recibir(pieza);
			horno.entregar();
			insertado = esmaltadora.recibir(pieza);
		}
		catch(Exception ex)
		{
		}
		
		assertTrue("No se pudo inserta una pieza en otra maquina luego de sacarla de su anterior.", insertado);
	}
	
	public void testPiezaConTransformacionesYMateriasPrimasNecesariasEsProducto()
	{
		Transformacion tornear = new Transformacion("Tornear");
		Transformacion cromar = new Transformacion("Cromar");		
		
		TipoMateriaPrima hierro = new TipoMateriaPrima("Hierro", 5.0, "Kg.");
		MateriaPrima pedazoHiero = new MateriaPrima(hierro, 50);
		
		TipoProducto tornillo = new TipoProducto("Tornillo", 10);

		tornillo.agregarTransformacion(tornear);
		tornillo.agregarTransformacion(cromar);
		tornillo.agregarMateriaPrima(pedazoHiero);
		
		List<MateriaPrima> materiasPrimas = new ArrayList<MateriaPrima>();
		materiasPrimas.add(new MateriaPrima(hierro, 50));
		
		Pieza pieza = null;
		
		try
		{
			pieza = new Pieza(materiasPrimas);
			tornear.transformar(pieza, 100);
			cromar.transformar(pieza, 100);
		}
		catch (Exception e) {}
		
		assertTrue("La pieza no se valido como un producto.", tornillo.esProducto(pieza));				
	}

	public void testPiezaSinTransformacionesNecesariasPeroMateriasPrimasNecesariasNoEsProducto()
	{
		Transformacion tornear = new Transformacion("Tornear");
		Transformacion cromar = new Transformacion("Cromar");		
		
		TipoMateriaPrima hierro = new TipoMateriaPrima("Hierro", 5.0, "Kg.");
		MateriaPrima pedazoHiero = new MateriaPrima(hierro, 50);
		
		TipoProducto tornillo = new TipoProducto("Tornillo", 10);

		tornillo.agregarTransformacion(tornear);
		tornillo.agregarTransformacion(cromar);
		tornillo.agregarMateriaPrima(pedazoHiero);
		
		List<MateriaPrima> materiasPrimas = new ArrayList<MateriaPrima>();
		materiasPrimas.add(new MateriaPrima(hierro, 50));
		
		Pieza pieza = null;
		
		try
		{
			pieza = new Pieza(materiasPrimas);
			tornear.transformar(pieza, 100);
		}
		catch (Exception e) {}
		
		assertFalse("La pieza se valido como un producto a pesar de no tener las transformaciones necesarias.", tornillo.esProducto(pieza));				
	}
	
	public void testPiezaConTransformacionesNecesariasSinMateriasPrimasNecesariasNoEsProducto()
	{
		Transformacion tornear = new Transformacion("Tornear");
		Transformacion cromar = new Transformacion("Cromar");		
		
		TipoMateriaPrima hierro = new TipoMateriaPrima("Hierro", 5.0, "Kg.");
		MateriaPrima pedazoHiero = new MateriaPrima(hierro, 50);
		
		TipoProducto tornillo = new TipoProducto("Tornillo", 10);

		tornillo.agregarTransformacion(tornear);
		tornillo.agregarTransformacion(cromar);
		tornillo.agregarMateriaPrima(pedazoHiero);
		
		List<MateriaPrima> materiasPrimas = new ArrayList<MateriaPrima>();
		materiasPrimas.add(new MateriaPrima(hierro, 10));
		
		Pieza pieza = null;
		
		try
		{
			pieza = new Pieza(materiasPrimas);
			tornear.transformar(pieza, 100);
			cromar.transformar(pieza, 100);
		}
		catch (Exception e) {}
		
		assertFalse("La pieza se valido como un producto a pesar de no tener las materias primas necesarias.", tornillo.esProducto(pieza));				
	}
}
